/* ----------------------------------------------------------------------------------------------------------------
 *  DelayManager
 * ----------------------------------------------------------------------------------------------------------------
 */
package pure.engine.system 
{
	import flash.utils.getTimer;
	
	use namespace ns_despair
	
	// 延迟管理器
	// [author] - Pure
	
	// [Hint] - 延迟方法调用管理器
	//
public class DelayManager implements IFrameObject
{

	public function DelayManager()
	{
		m_delayProp = new Vector.<DelayObject>();
		m_delayProp.push(null);
	}
	

	
	
	
	//======================
	// Base
	//======================

	
	// 延迟调用
	public function delayedCall(delay:Number, callback:Function, ...args):void
	{
		var delayObject:DelayObject;
		
		if(!m_started)
		{
			ProcessManager.instance.addFrameObject(this, 20);
			m_baseTime  =  getTimer();
			m_started   =  true;
		}
		
		m_delayProp[++m_numDelay] = (delayObject = new DelayObject());
		delayObject.delay = delay * 1000.0 + m_baseTime;
		delayObject.callback = callback;
		delayObject.params = args;
		_advanceForPush(m_numDelay);
	}

	
	// 清除
	public function reset():void
	{
		ProcessManager.instance.removeFrameObject(this);
		m_started           =  false;
		m_delayProp.length  =  1;
		m_numDelay          =  0;
	}

	
	// 计时
	public function onFrame(elapsedT:Number):void
	{
		var delayObject:DelayObject;
		while (m_delayProp[1].delay <= (m_baseTime += elapsedT))
		{
			delayObject = this.shift();
			delayObject.callback.call(delayObject.params);
			if (m_numDelay <= 0)
			{
				return;
			}
		}
	}
	
	
	
	
	/* ----------------------------------------------------------------------------------------------------------------
	 * ★★★★★★★★★★★★★★★★★★★★★  private  ★★★★★★★★★★★★★★★★★★★★★
	 * ----------------------------------------------------------------------------------------------------------------
	 */
	

	 
	 
	// 移除并获取首项
	
	// [Feature]
	// ① 父节点 ---- prev = (N-1/2) >> 0
	// ② 子节点 ---- next = N*2+1 或 N*2+2
	private function shift():DelayObject
	{
		var result:DelayObject, temp:DelayObject;
		var node:int, oldNode:int, prev:int;
		
		if (m_numDelay == 0)  return null;
		
		if (m_numDelay == 1) 
		{
			m_numDelay--;
			ProcessManager.instance.removeFrameObject(this);
			m_started = false;
			return m_delayProp.pop();
		}
		
		result = m_delayProp[1];
		node = 1;
		
		m_delayProp[1] = m_delayProp.pop();
		
		while (true)
		{
			oldNode = node;
			prev = node * 2;
			if (prev < m_delayProp.length)
			{
				if (m_delayProp[prev].delay < m_delayProp[node].delay)
				{
					node = prev;
				}
				
				//如果另一个子节点更小
				if (prev + 1 < m_delayProp.length && m_delayProp[prev + 1].delay < m_delayProp[node].delay)
				{
					node = prev + 1;
				}
			}
			
			if (node != oldNode)
			{
				temp = m_delayProp[node];
				m_delayProp[node] = m_delayProp[oldNode];
				m_delayProp[oldNode] = temp;
			}	
			else
			{
				break;
			}
		} 
		
		m_numDelay--
		return result;
	}
	

	
	
	// 插入后更新
	private function _advanceForPush(index:int):void
	{
		var prev:int, temp:DelayObject;
		
		while (index > 1)
		{
			prev = index >> 1;
			if (m_delayProp[index].delay < m_delayProp[prev].delay)
			{
				temp                =  m_delayProp[index];
				m_delayProp[index]  =  m_delayProp[prev];
				m_delayProp[prev]   =  temp;
				index               =  prev;
			}
			else
			{
				break;
			}
		} 
	}
	
	
	
	//======================
	// Member
	//======================
	
	
	private var m_delayProp:Vector.<DelayObject>;  //需要注意的是，二叉堆数据的下标是从1开始排列的
	
	private var m_numDelay:int;  // 总数

	private var m_started:Boolean;
	
	private var m_baseTime:int;
	
}

}


class DelayObject
{
	
	public var delay:int;  // 延迟时间
	
	public var callback:Function;  // 回调
	
	public var params:Array;  // 参数
	
	
}